package com.loong.android.sqlite;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.text.TextUtils;
import android.util.Log;

import com.loong.android.sqlite.data.DbData;
import com.loong.android.sqlite.data.EntityFieldData;
import com.loong.android.sqlite.data.TableData;
import com.loong.android.sqlite.utils.DataBaseUtils;

import java.lang.reflect.Field;
import java.util.List;

/**
 * SQLite数据库操作类
 * 需要手动添加权限：android.permission.ACCESS_COARSE_LOCATION、android.permission.ACCESS_FINE_LOCATION
 */
public class SQLite {
    private final static String TAG = "Sqlite";

    /**
     * 判断表是否已注册
     *
     * @param dbName    数据库名称
     * @param tableName 表名称
     */
    public static boolean tableIsRegister(String dbName, String tableName) {
        return getTableData(dbName, tableName) != null;
    }

    /**
     * 获取已注册表的数据
     *
     * @param dbName    数据库名称
     * @param tableName 表名称
     */
    private static TableData getTableData(String dbName, String tableName) {
        if (TextUtils.isEmpty(dbName) || TextUtils.isEmpty(tableName)) return null;
        DbData dbData = DataBaseUtils.getDbData(dbName);
        if (dbData == null || dbData.getTableList() == null) return null;
        for (TableData TableData : dbData.getTableList()) {
            if (TableData == null || TextUtils.isEmpty(TableData.getTableName())) continue;
            if (!TableData.getTableName().equals(tableName)) continue;
            return TableData;
        }
        return null;
    }

    /**
     * 初始化数据库，如果数据库已存在，则加载已存在的数据库。
     * 若本地已存在的数据库版本低于当前初始化的数据库版本，则初始化操作会删除之前的数据库并建立新的数据库，
     * 将旧的数据库数据迁移到新的数据库中。需要注意的是，每当数据库中任何一个表的任何字段在增删改后，初始化数据库
     * 时都需要提升数据库版本号，以便执行的删除重建以及数据迁移，否则可能导致程序意外崩溃。
     *
     * @param dbName 数据库名称(同db文件名称)
     * @param dbVersion 数据库的版本，最低值为1
     */
    public static void registerDataBase(String dbName, int dbVersion) {
        String dbFileName = dbName;
        dbFileName = dbFileName.endsWith(".db") ? dbFileName : dbFileName + ".db";
        DbData dbData = new DbData();
        dbData.setDbName(dbName);
        dbData.setDbFileName(dbFileName);
        dbData.setVersion(dbVersion);
        DataBaseUtils.mDbList.put(dbName, dbData);
    }

    /**
     * 在初始化数据库后，注册该数据库所有拥有的表，只有注册过得表才能使用。
     *
     * @param dbName 数据库名称
     * @param tableName 待注册的表名称
     * @param tableEntityClass 待注册的表实体类
     */
    public static boolean registerTable(String dbName, String tableName, Object tableEntityClass) {
        if (TextUtils.isEmpty(dbName) || TextUtils.isEmpty(tableName) || tableEntityClass == null) return false;
        //获得实体内的字段数据
        List<EntityFieldData> tmpList = CommonEntityDao.handleEntityKeys((Class<?>) tableEntityClass);
        if (tmpList == null || tmpList.size() <= 0) return false;
        DbData dbData = DataBaseUtils.getDbData(dbName);
        if (dbData == null) return false;

        TableData tableData = getTableData(dbName, tableName);
        if (tableData != null) return false;

        tableData = new TableData();
        tableData.setTableName(tableName);
        tableData.setTableClass((Class<?>) tableEntityClass);
        tableData.setColumnKeyList(tmpList);
        dbData.addTableData(tableData);

        return true;
    }

    /**
     * 在执行"registerDataBase()"和"registerTable()"之后，调用本函数，提交注册的数据和数据库的表。
     * @param dbName 待提交的数据库名称
     */
    public static boolean commitDataBase(Context context, String dbName) {
        if (TextUtils.isEmpty(dbName)) return false;
        final DbData dbData = DataBaseUtils.getDbData(dbName);
        if (dbData == null) return false;
        SQLiteOpenHelper sqLiteOpenHelper = new SQLiteOpenHelper(context, dbData.getDbFileName(), null, dbData.getVersion()) {
            /**数据库创建*/
            @Override
            public void onCreate(SQLiteDatabase db) {
                if (TextUtils.isEmpty(dbData.getDbName())) return;
                Log.e("DatabaseHelper", "onCreate: " + dbData.getDbName());
                MigrationHelper.createDbAllTable(db, dbData, true);
            }

            /**数据库更新*/
            @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
                Log.e("ReleaseOpenHelper", "---oldVersion:" + oldVersion + ",newVersion:" + newVersion);
                if (newVersion > oldVersion) {
                    MigrationHelper.migrate(db, dbData);
                }
            }
        };
        SQLiteDatabase sqLiteDatabase = sqLiteOpenHelper.getWritableDatabase();
        if (sqLiteDatabase == null) return false;
        dbData.setSqLiteDatabase(sqLiteDatabase);
        return true;
    }

    /**
     * 取数据库SqLiteDatabase对象
     *
     * @param dbName 数据库名称
     */
    public static Object getDataBase(String dbName) {
        if (TextUtils.isEmpty(dbName)) return null;
        DbData dbData = DataBaseUtils.getDbData(dbName);
        if (dbData == null) return null;
        return dbData.getSqLiteDatabase();
    }

    /**
     * 执行删除，返回删除影响的记录行数，删除失败返回-1.
     *
     * @param dbName 待删除记录的数据库名称
     * @param tableName  待删除记录的表名称
     * @param conditions 待删除记录的条件，如："column=‘abc’ or ccc=1"，支持传入过个删除条件，多个删除条件之间为"and"的关系.
     */
    public static int delete(String dbName, String tableName, String... conditions) {
        if (TextUtils.isEmpty(dbName) || TextUtils.isEmpty(tableName)) return -1;
        DbData dbData = DataBaseUtils.getDbData(dbName);
        if (dbData == null || dbData.getSqLiteDatabase() == null) return -1;
        String delFilter = "";
        if(conditions != null && conditions.length > 0) {
            for (String s : conditions) {
                delFilter = delFilter.equals("") ? "(" + s + ")" : delFilter + " and (" + s + ")";
            }
        }
        return dbData.getSqLiteDatabase().delete(tableName, delFilter, null);
    }

    /**
     * 删除某个数据库某个表的所有记录
     *
     * @param dbName 待删除记录的数据库名称
     * @param tableName 待删除记录的表名称
     */
    public static int deleteAll(String dbName, String tableName) {
        return delete(dbName, tableName, "1");
    }

    /**
     * 重置某个数据库某个表的自增ID，使之从重新从1开始自增。
     *
     * @param dbName 待重置的数据库名称
     * @param tableName 待重置的表名称
     */
    public static void resetTableId(String dbName, String tableName) {
        if (TextUtils.isEmpty(dbName) || TextUtils.isEmpty(tableName)) return;
        DbData dbData = DataBaseUtils.getDbData(dbName);
        if (dbData == null || dbData.getSqLiteDatabase() == null) return;
        dbData.getSqLiteDatabase().execSQL("DELETE FROM " + tableName);
        dbData.getSqLiteDatabase().execSQL("DELETE FROM sqlite_sequence WHERE name = '" + tableName + "'");
    }

    /**
     * 获取某个数据库中某个表的总记录数
     *
     * @param dbName 待待获取记录数的数据库名称
     * @param tableName 待获取记录数的表名称
     */
    public static long count(String dbName, String tableName) {
        if (TextUtils.isEmpty(dbName) || TextUtils.isEmpty(tableName)) return 0;
        DbData dbData = DataBaseUtils.getDbData(dbName);
        if (dbData == null || dbData.getSqLiteDatabase() == null) return 0;
        Cursor cursor = dbData.getSqLiteDatabase().rawQuery("select count(*) from " + tableName,null);
        cursor.moveToFirst();
        long count = cursor.getLong(0);
        cursor.close();
        return count;
    }


    /**
     * 向某个表插入一条记录，返回成功插入的记录数，失败返回-1
     *
     * @param dbName 待插入记录的数据名称
     * @param tableName   待插入记录的表名称
     * @param entity  待插入记录的表实体数据
     */
    public static long insert(String dbName, String tableName, Object entity) {
        if (TextUtils.isEmpty(dbName) || TextUtils.isEmpty(tableName) || entity == null) return -1;

        DbData dbData = DataBaseUtils.getDbData(dbName);
        if (dbData == null) return -1;
        SQLiteDatabase database = dbData.getSqLiteDatabase();
        if (database == null) return -1;

        Field[] fieldList = entity.getClass().getDeclaredFields();
        if (fieldList == null || fieldList.length <= 0) return -1;

        ContentValues values = new ContentValues();
        for (Field field : fieldList) {
            if (field == null) continue;
            field.setAccessible(true);
            String name = field.getName();
            if (TextUtils.isEmpty(name) || name.length() <= 3) continue;
            if (!name.substring(0, 3).equalsIgnoreCase("db_")) continue;
            if (name.equals(CommonEntity.ID_KEY)) continue;
            String type = field.getType().getSimpleName();
            if (type == null) continue;
            try {
                if (type.equalsIgnoreCase("string")) {
                    values.put(name, (String) field.get(entity));
                } else if (type.equalsIgnoreCase("boolean")) {
                    values.put(name, (boolean) field.get(entity) ? 1L : 0L);
                } else if (type.equalsIgnoreCase("short")) {
                    values.put(name, (short) field.get(entity));
                } else if (type.equalsIgnoreCase("integer")) {
                    values.put(name, (int) field.get(entity));
                } else if (type.equalsIgnoreCase("long")) {
                    values.put(name, (long) field.get(entity));
                } else if (type.equalsIgnoreCase("float")) {
                    values.put(name, (float) field.get(entity));
                } else if (type.equalsIgnoreCase("double")) {
                    values.put(name, (double) field.get(entity));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return database.insert(tableName, null, values);
    }

    /**
     * 执行sql语句
     * @param dbName 数据库名称
     * @param sql sql语句
     */
    public static void execSQL(String dbName, String sql) {
        DbData dbData = DataBaseUtils.getDbData(dbName);
        if (dbData == null || dbData.getSqLiteDatabase() == null) return;
        dbData.getSqLiteDatabase().execSQL(sql);
    }






}
